﻿using System;
using UnityEngine;

[AddComponentMenu("FingerGestures/Toolbox/Misc/DragOrbit")]
public class TBDragOrbit : MonoBehaviour
{
    public bool allowPanning;
    public bool allowPinchZoom = true;
    public bool clampPitchAngle = true;
    private float distance = 10f;
    private float idealDistance;
    private Vector3 idealPanOffset = Vector3.zero;
    private float idealPitch;
    private float idealYaw;
    public float initialDistance = 10f;
    public bool invertPanningDirections;
    private float lastPanTime;
    public float maxDistance = 20f;
    public float maxPitch = 80f;
    public float minDistance = 1f;
    public float minPitch = -20f;
    public Transform panningPlane;
    public float panningSensitivity = 1f;
    private Vector3 panOffset = Vector3.zero;
    public float pinchZoomSensitivity = 2f;
    private float pitch;
    public float pitchSensitivity = 80f;
    public bool smoothMotion = true;
    public float smoothOrbitSpeed = 4f;
    public bool smoothPanning = true;
    public float smoothPanningSpeed = 8f;
    public float smoothZoomSpeed = 3f;
    public Transform target;
    private float yaw;
    public float yawSensitivity = 80f;

    private void Apply()
    {
        if (this.smoothMotion)
        {
            this.distance = Mathf.Lerp(this.distance, this.IdealDistance, Time.deltaTime * this.smoothZoomSpeed);
            this.yaw = Mathf.Lerp(this.yaw, this.IdealYaw, Time.deltaTime * this.smoothOrbitSpeed);
            this.pitch = Mathf.Lerp(this.pitch, this.IdealPitch, Time.deltaTime * this.smoothOrbitSpeed);
        }
        else
        {
            this.distance = this.IdealDistance;
            this.yaw = this.IdealYaw;
            this.pitch = this.IdealPitch;
        }
        if (this.smoothPanning)
        {
            this.panOffset = Vector3.Lerp(this.panOffset, this.idealPanOffset, Time.deltaTime * this.smoothPanningSpeed);
        }
        else
        {
            this.panOffset = this.idealPanOffset;
        }
        base.transform.rotation = Quaternion.Euler(this.pitch, this.yaw, 0f);
        base.transform.position = (this.target.position + this.panOffset) - ((Vector3) (this.distance * base.transform.forward));
    }

    private static float ClampAngle(float angle, float min, float max)
    {
        if (angle < -360f)
        {
            angle += 360f;
        }
        if (angle > 360f)
        {
            angle -= 360f;
        }
        return Mathf.Clamp(angle, min, max);
    }

    private void FingerGestures_OnDragMove(Vector2 fingerPos, Vector2 delta)
    {
        if (((Time.time - this.lastPanTime) >= 0.25f) && (this.target != null))
        {
            this.IdealYaw += (delta.x * this.yawSensitivity) * 0.02f;
            this.IdealPitch -= (delta.y * this.pitchSensitivity) * 0.02f;
        }
    }

    private void FingerGestures_OnPinchMove(Vector2 fingerPos1, Vector2 fingerPos2, float delta)
    {
        if (this.allowPinchZoom)
        {
            this.IdealDistance -= delta * this.pinchZoomSensitivity;
        }
    }

    private void FingerGestures_OnTwoFingerDragMove(Vector2 fingerPos, Vector2 delta)
    {
        if (this.allowPanning)
        {
            Vector3 vector = (Vector3) ((-0.02f * this.panningSensitivity) * ((this.panningPlane.right * delta.x) + (this.panningPlane.up * delta.y)));
            if (this.invertPanningDirections)
            {
                this.IdealPanOffset -= vector;
            }
            else
            {
                this.IdealPanOffset += vector;
            }
            this.lastPanTime = Time.time;
        }
    }

    private void LateUpdate()
    {
        this.Apply();
    }

    private void OnDisable()
    {
        FingerGestures.OnDragMove -= new FingerGestures.DragMoveEventHandler(this.FingerGestures_OnDragMove);
        FingerGestures.OnPinchMove -= new FingerGestures.PinchMoveEventHandler(this.FingerGestures_OnPinchMove);
        FingerGestures.OnTwoFingerDragMove -= new FingerGestures.DragMoveEventHandler(this.FingerGestures_OnTwoFingerDragMove);
    }

    private void OnEnable()
    {
        FingerGestures.OnDragMove += new FingerGestures.DragMoveEventHandler(this.FingerGestures_OnDragMove);
        FingerGestures.OnPinchMove += new FingerGestures.PinchMoveEventHandler(this.FingerGestures_OnPinchMove);
        FingerGestures.OnTwoFingerDragMove += new FingerGestures.DragMoveEventHandler(this.FingerGestures_OnTwoFingerDragMove);
    }

    public void ResetPanning()
    {
        this.IdealPanOffset = Vector3.zero;
    }

    private void Start()
    {
        if (this.panningPlane == null)
        {
            this.panningPlane = base.transform;
        }
        Vector3 eulerAngles = base.transform.eulerAngles;
        float initialDistance = this.initialDistance;
        this.IdealDistance = initialDistance;
        this.distance = initialDistance;
        initialDistance = eulerAngles.y;
        this.IdealYaw = initialDistance;
        this.yaw = initialDistance;
        initialDistance = eulerAngles.x;
        this.IdealPitch = initialDistance;
        this.pitch = initialDistance;
        if (base.rigidbody != null)
        {
            base.rigidbody.freezeRotation = true;
        }
        this.Apply();
    }

    public float Distance
    {
        get
        {
            return this.distance;
        }
    }

    public float IdealDistance
    {
        get
        {
            return this.idealDistance;
        }
        set
        {
            this.idealDistance = Mathf.Clamp(value, this.minDistance, this.maxDistance);
        }
    }

    public Vector3 IdealPanOffset
    {
        get
        {
            return this.idealPanOffset;
        }
        set
        {
            this.idealPanOffset = value;
        }
    }

    public float IdealPitch
    {
        get
        {
            return this.idealPitch;
        }
        set
        {
            this.idealPitch = !this.clampPitchAngle ? value : ClampAngle(value, this.minPitch, this.maxPitch);
        }
    }

    public float IdealYaw
    {
        get
        {
            return this.idealYaw;
        }
        set
        {
            this.idealYaw = value;
        }
    }

    public Vector3 PanOffset
    {
        get
        {
            return this.panOffset;
        }
    }

    public float Pitch
    {
        get
        {
            return this.pitch;
        }
    }

    public float Yaw
    {
        get
        {
            return this.yaw;
        }
    }

    public enum PanMode
    {
        Disabled,
        OneFinger,
        TwoFingers
    }
}

